package com.qzsoft.zhjd.asphalt.modules.asphaltmatch.service.impl;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import com.qzsoft.jeemis.common.utils.ConvertDictUtils;
import com.qzsoft.jeemis.common.validator.ValidatorUtils;
import com.qzsoft.zhjd.asphalt.modules.asphaltmatch.dto.AsphaltMatchHotForAppDataDetailsDto;
import com.qzsoft.zhjd.asphalt.modules.asphaltmatch.dto.AsphaltMatchHotForAppDataDto;
import com.qzsoft.zhjd.asphalt.modules.asphaltmatch.dto.AsphaltMatchHotForAppDto;
import com.qzsoft.zhjd.asphalt.modules.asphaltmatch.entity.AsphaltMatchEntity;
import com.qzsoft.zhjd.asphalt.modules.asphaltmatch.entity.AsphaltMatchHotEntity;
import com.qzsoft.zhjd.asphalt.modules.asphaltmatch.entity.AsphaltMatchTypeEntity;
import com.qzsoft.zhjd.asphalt.modules.asphaltmatch.mapper.AsphaltMatchHotMapper;
import com.qzsoft.zhjd.asphalt.modules.asphaltmatch.service.AsphaltMatchHotService;
import com.qzsoft.zhjd.asphalt.modules.asphaltmatch.service.AsphaltMatchService;
import com.qzsoft.zhjd.asphalt.modules.asphaltmatch.service.AsphaltMatchTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qzsoft.zhjd.common.enums.BizCode;
import com.qzsoft.zhjd.common.utils.RenExceptionUtils;

/**
 * @ClassName AsphaltMatchHotServiceImpl
 * @Description 生产配比热料筛分级配业务接口实现
 * @author linhuawei
 * @since 2021-11-22
 */
@Service
public class AsphaltMatchHotServiceImpl extends ServiceImpl<AsphaltMatchHotMapper, AsphaltMatchHotEntity>
        implements AsphaltMatchHotService {

    @Autowired
    private AsphaltMatchService asphaltMatchService;

    @Autowired
    private AsphaltMatchTypeService asphaltMatchTypeService;

    @Override
    public List<AsphaltMatchHotEntity> listByMatchId(Serializable matchId) {
        // 获取级配信息
        AsphaltMatchEntity match = asphaltMatchService.getById(matchId);
        if (null == match) {
            RenExceptionUtils.throwEx(BizCode.PARAMS_ERROR, "设计生产级配不存在");
        }

        // 获取级配类型
        AsphaltMatchTypeEntity matchType = asphaltMatchTypeService.getByType(match.getMatchType());
        if (null == matchType) {
            return new ArrayList<AsphaltMatchHotEntity>();
        }

        // 获取当前已经设置的信息
        QueryWrapper<AsphaltMatchHotEntity> queryWrapper = new QueryWrapper<AsphaltMatchHotEntity>();
        queryWrapper.eq("match_id", matchId);
        queryWrapper.orderByAsc("sieve_size");
        List<AsphaltMatchHotEntity> list = baseMapper.selectList(queryWrapper);
        Map<String, AsphaltMatchHotEntity> map = new HashMap<>();
        BigDecimal sieveSize;
        if (ObjectUtils.isNotEmpty(list)) {
            for (AsphaltMatchHotEntity item : list) {
                sieveSize = item.getSieveSize();
                if (null != sieveSize) {
                    map.put(sieveSize.stripTrailingZeros().toPlainString(), item);
                }
            }
        }

        // 根据级配类型筛选出需要显示的数据，防止级配做了修改，数据有差异情况
        JSONArray sieveArray = matchType.getSieveArray();
        List<AsphaltMatchHotEntity> result = new ArrayList<AsphaltMatchHotEntity>();
        if (null != sieveArray) {

            AsphaltMatchHotEntity entity;
            for (int i = 0, len = sieveArray.size(); i < len; i++) {
                try {
                    sieveSize = sieveArray.getBigDecimal(i);
                    if (null != sieveSize) {
                        entity = map.get(sieveSize.stripTrailingZeros().toPlainString());
                        if (null == entity) {
                            entity = new AsphaltMatchHotEntity();
                            entity.setMatchId(match.getId());
                            entity.setSieveSize(sieveSize);
                        }
                        result.add(entity);
                    }
                } catch (Exception e) {
                }
            }
        }
        return result;
    }

    @Override
    public AsphaltMatchHotForAppDto infoForApp(String matchId) {
        // 获取级配信息
        AsphaltMatchEntity match = asphaltMatchService.getById(matchId);
        if (null == match) {
            RenExceptionUtils.throwEx(BizCode.PARAMS_ERROR, "未知的生产配比");
        }

        // 获取级配类型
        AsphaltMatchTypeEntity matchType = asphaltMatchTypeService.getByType(match.getMatchType());
        if (null == matchType) {
            RenExceptionUtils.throwEx(BizCode.PARAMS_ERROR, "未知的级配类型");
        }
        JSONArray sieveArray = matchType.getSieveArray();
        if (null == sieveArray) {
            RenExceptionUtils.throwEx(BizCode.PARAMS_ERROR, "当前生产配比未设置筛孔数据");
        }

        // 计算筛孔数据
        Map<String, AsphaltMatchHotForAppDataDto> sieveMap = new LinkedHashMap<>();
        BigDecimal sieveSize;
        String sieveSizeStr;
        AsphaltMatchHotForAppDataDto dataDto;
        for (int i = 0, len = sieveArray.size(); i < len; i++) {
            try {
                sieveSize = sieveArray.getBigDecimal(i);
                if (null != sieveSize) {
                    sieveSizeStr = sieveSize.stripTrailingZeros().toPlainString();
                    dataDto = new AsphaltMatchHotForAppDataDto();
                    dataDto.setSieveSize(sieveSize);
                    dataDto.setMap(new LinkedHashMap<>());
                    dataDto.getMap().put("target", new AsphaltMatchHotForAppDataDetailsDto("设计生产配比", "target", null));
                    if (match.inUse(match.getGravel1Name(), match.getGravel1())) {
                        dataDto.getMap().put("gravel1",
                                new AsphaltMatchHotForAppDataDetailsDto(match.getGravel1Name(), "gravel1", null));
                    }
                    if (match.inUse(match.getGravel2Name(), match.getGravel2())) {
                        dataDto.getMap().put("gravel2",
                                new AsphaltMatchHotForAppDataDetailsDto(match.getGravel2Name(), "gravel2", null));
                    }
                    if (match.inUse(match.getGravel3Name(), match.getGravel3())) {
                        dataDto.getMap().put("gravel3",
                                new AsphaltMatchHotForAppDataDetailsDto(match.getGravel3Name(), "gravel3", null));
                    }
                    if (match.inUse(match.getGravel4Name(), match.getGravel4())) {
                        dataDto.getMap().put("gravel4",
                                new AsphaltMatchHotForAppDataDetailsDto(match.getGravel4Name(), "gravel4", null));
                    }
                    if (match.inUse(match.getGravel5Name(), match.getGravel5())) {
                        dataDto.getMap().put("gravel5",
                                new AsphaltMatchHotForAppDataDetailsDto(match.getGravel5Name(), "gravel5", null));
                    }
                    if (match.inUse(match.getGravel6Name(), match.getGravel6())) {
                        dataDto.getMap().put("gravel6",
                                new AsphaltMatchHotForAppDataDetailsDto(match.getGravel6Name(), "gravel6", null));
                    }
                    if (match.inUse(match.getPowder1Name(), match.getPowder1())) {
                        dataDto.getMap().put("powder1",
                                new AsphaltMatchHotForAppDataDetailsDto(match.getPowder1Name(), "powder1", null));
                    }
                    if (match.inUse(match.getPowder2Name(), match.getPowder2())) {
                        dataDto.getMap().put("powder2",
                                new AsphaltMatchHotForAppDataDetailsDto(match.getPowder2Name(), "powder2", null));
                    }
                    if (match.inUse(match.getPowder3Name(), match.getPowder3())) {
                        dataDto.getMap().put("powder3",
                                new AsphaltMatchHotForAppDataDetailsDto(match.getPowder3Name(), "powder3", null));
                    }
                    if (match.inUse(null, match.getRecycledMaterial())) {
                        dataDto.getMap().put("recycledMaterial",
                                new AsphaltMatchHotForAppDataDetailsDto("再生料", "recycledMaterial", null));
                    }
                    sieveMap.put(sieveSizeStr, dataDto);
                }
            } catch (Exception e) {
            }
        }

        // 获取已经配置的筛孔数据
        QueryWrapper<AsphaltMatchHotEntity> queryWrapper = new QueryWrapper<AsphaltMatchHotEntity>();
        queryWrapper.eq("match_id", matchId);
        queryWrapper.orderByAsc("sieve_size");
        List<AsphaltMatchHotEntity> list = baseMapper.selectList(queryWrapper);
        AsphaltMatchHotForAppDataDetailsDto detailsDto;
        for (AsphaltMatchHotEntity entity : list) {
            sieveSize = entity.getSieveSize();
            sieveSizeStr = sieveSize.stripTrailingZeros().toPlainString();
            dataDto = sieveMap.get(sieveSizeStr);
            if (null == dataDto) {
                continue;
            }

            detailsDto = dataDto.getMap().get("target");
            if (null != detailsDto) {
                detailsDto.setValue(entity.getTarget());
            }
            detailsDto = dataDto.getMap().get("gravel1");
            if (null != detailsDto) {
                detailsDto.setValue(entity.getGravel1());
            }
            detailsDto = dataDto.getMap().get("gravel2");
            if (null != detailsDto) {
                detailsDto.setValue(entity.getGravel2());
            }
            detailsDto = dataDto.getMap().get("gravel3");
            if (null != detailsDto) {
                detailsDto.setValue(entity.getGravel3());
            }
            detailsDto = dataDto.getMap().get("gravel4");
            if (null != detailsDto) {
                detailsDto.setValue(entity.getGravel4());
            }
            detailsDto = dataDto.getMap().get("gravel5");
            if (null != detailsDto) {
                detailsDto.setValue(entity.getGravel5());
            }
            detailsDto = dataDto.getMap().get("gravel6");
            if (null != detailsDto) {
                detailsDto.setValue(entity.getGravel6());
            }
            detailsDto = dataDto.getMap().get("powder1");
            if (null != detailsDto) {
                detailsDto.setValue(entity.getPowder1());
            }
            detailsDto = dataDto.getMap().get("powder2");
            if (null != detailsDto) {
                detailsDto.setValue(entity.getPowder2());
            }
            detailsDto = dataDto.getMap().get("powder3");
            if (null != detailsDto) {
                detailsDto.setValue(entity.getPowder3());
            }
            detailsDto = dataDto.getMap().get("recycledMaterial");
            if (null != detailsDto) {
                detailsDto.setValue(entity.getRecycledMaterial());
            }
        }

        // 转化map对象
        List<AsphaltMatchHotForAppDataDto> data = new ArrayList<AsphaltMatchHotForAppDataDto>();
        sieveMap.forEach((key, value) -> {
            List<AsphaltMatchHotForAppDataDetailsDto> detailsList = new ArrayList<>();
            if (null != value.getMap()) {
                value.getMap().forEach((key1, value1) -> {
                    detailsList.add(value1);
                });
            }
            value.setDetails(detailsList);
            data.add(value);
        });

        // 返回结果数据
        AsphaltMatchHotForAppDto dto = new AsphaltMatchHotForAppDto();
        dto.setMatchId(matchId);
        dto.setMatchType(match.getMatchType());
        dto.setMatchName(match.getMatchName());
        dto.setMatchCode(match.getMatchCode());
        dto.setPavingLevel(match.getPavingLevel());
        dto.setData(data);
        return ConvertDictUtils.formatDicData(dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(AsphaltMatchHotEntity entity) {
        // 判断配方是否存在
        AsphaltMatchEntity match = asphaltMatchService.getById(entity.getMatchId());
        if (null == match) {
            RenExceptionUtils.throwEx(BizCode.PARAMS_ERROR, "未知的生产配比");
        }

        // 判断筛孔是否存在
        AsphaltMatchTypeEntity type = asphaltMatchTypeService.getByType(match.getMatchType());
        if (null == type) {
            RenExceptionUtils.throwEx(BizCode.PARAMS_ERROR, "未知的级配类型");
        }
        JSONArray sieveArray = type.getSieveArray();
        if (null == sieveArray) {
            RenExceptionUtils.throwEx(BizCode.PARAMS_ERROR, "当前生产配比未设置筛孔数据");
        }
        BigDecimal sieveSize = entity.getSieveSize();
        boolean inArray = false;
        for (int i = 0, len = sieveArray.size(); i < len; i++) {
            if (0 == sieveSize.compareTo(sieveArray.getBigDecimal(i))) {
                inArray = true;
                break;
            }
        }
        if (!inArray) {
            RenExceptionUtils.throwEx(BizCode.PARAMS_ERROR, "当前生产配比未设置[" + sieveSize + "]筛孔");
        }

        // 删除已经存在的筛孔数据
        QueryWrapper<AsphaltMatchHotEntity> queryWrapper = new QueryWrapper<AsphaltMatchHotEntity>();
        queryWrapper.eq("match_id", entity.getMatchId());
        queryWrapper.eq("sieve_size", sieveSize);
        baseMapper.delete(queryWrapper);

        // 更新配比热料配置状态
        if(null == match.getHotConfig() || 0 == match.getHotConfig()) {
            asphaltMatchService.updateHotConfig(entity.getMatchId(), 1);
        }

        // 保存筛孔数据
        return super.save(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(List<AsphaltMatchHotEntity> list, String matchId) {
        // 删除已经存在的数据
        QueryWrapper<AsphaltMatchHotEntity> queryWrapper = new QueryWrapper<AsphaltMatchHotEntity>();
        queryWrapper.eq("match_id", matchId);
        baseMapper.delete(queryWrapper);

        // 添加新的数据
        list.forEach(item -> {
            item.setId(null);
            item.setMatchId(matchId);
        });
        list.stream().forEach(t -> {
            ValidatorUtils.validateEntity(t);
        });
        saveBatch(list);

        // 更新配比热料配置状态
        asphaltMatchService.updateHotConfig(matchId, 1);
    }

    @Override
    public void deleteByMatchId(Serializable matchId) {
        QueryWrapper<AsphaltMatchHotEntity> queryWrapper = new QueryWrapper<AsphaltMatchHotEntity>();
        queryWrapper.eq("match_id", matchId);
        baseMapper.delete(queryWrapper);
    }

    @Override
    public Map<String, BigDecimal> getTargetMap(String matchId) {
        QueryWrapper<AsphaltMatchHotEntity> queryWrapper = new QueryWrapper<AsphaltMatchHotEntity>();
        queryWrapper.eq("match_id", matchId);
        queryWrapper.orderByAsc("sieve_size");
        List<AsphaltMatchHotEntity> list = baseMapper.selectList(queryWrapper);

        Map<String, BigDecimal> result = new HashMap<String, BigDecimal>();
        if (ObjectUtils.isNotEmpty(list)) {
            String sieve;
            for (AsphaltMatchHotEntity item : list) {
                if (null != item.getSieveSize()) {
                    sieve = item.getSieveSize().stripTrailingZeros().toPlainString();
                    sieve = sieve.replace(".", "d");
                    result.put(sieve, item.getTarget());
                }
            }
        }

        return result;
    }

}
